//=========================================================
// 鏂囦欢锛歮ap_service.h
// 鎻忚堪锛氬湴鍥炬湇鍔＄被瀹氫箟锛屽鐞嗗湴鍥剧浉鍏冲姛鑳藉拰璺嚎瑙勫垝
//=========================================================

#ifndef MAP_SERVICE_H
#define MAP_SERVICE_H

// 鍩烘湰鏍囧噯搴撳ご鏂囦欢
#include <string>
#include <vector>
#include <utility>
#include <cstdint>
#include <cmath>

// 鍓嶅悜澹版槑
class Place;
class PlaceDB;

// Windows鐗瑰畾澶存枃浠
#ifdef _WIN32
#define WIN32_LEAN_AND_MEAN
#define NOMINMAX
#include <windows.h>
#include <winsock2.h>
#include <ws2tcpip.h>
#endif

// 澶栭儴搴撳ご鏂囦欢
#include <curl/curl.h>
#include "crow_all.h"
#include "nlohmann/json.hpp"
#include <sqlite3.h>

// 蹇呰鐨勯」鐩ご鏂囦欢
#include "models/place.h"
#include "models/route.h"
#include "database/place_db.h"

/**
 * 鍦板浘鏈嶅姟绫 - 澶勭悊鍦板浘鐩稿叧鍔熻兘鍜岃矾绾胯鍒
 */
class MapService {
private:
    std::string ak;
    crow::SimpleApp& app_;
    std::string dbPath_;
    
    // 服务端API密钥数组和当前索引（用于轮换使用分散额度）
    std::vector<std::string> serverAks;
    int currentServerAkIndex;
    
    // 纭繚璺綉鐩稿叧琛ㄥ瓨鍦
    void ensurePathTablesExist();
    
    // API密钥轮换方法
    void rotateServerAk();
    
public:
    // 鏋勯€犲嚱鏁
    MapService(const std::string& apiKey);
    MapService(crow::SimpleApp& app, const std::string& dbPath);
    
    // 鍩烘湰鍔熻兘
    static size_t WriteCallback(void* contents, size_t size, size_t nmemb, void* userp);
    crow::response getMapPage();
    crow::response getSinglePlaceMapPage();
    crow::json::wvalue convertPlacesToJson(const std::vector<Place>& places);
    std::string getRoutePlan(double startLat, double startLng, double endLat, double endLng, const std::string& mode = "driving");
    static crow::response proxyRouteApi(double startLat, double startLng, double endLat, double endLng, const std::string& mode, const std::string& ak);
    
    // 支持密钥轮换的路线规划API调用
    crow::response proxyRouteApiWithRetry(double startLat, double startLng, double endLat, double endLng, const std::string& mode);
    
    // 鍦扮悊缂栫爜鍔熻兘
    std::pair<double, double> geocode(const std::string& address);
    std::string reverseGeocode(double lat, double lng);
    std::string getPoiData(const std::string& query, int pageNum = 0);
    std::string getPlaceOutline(const std::string& placeName);
    
    // 璺敱鍔熻兘
    static void setupMapRoutes(crow::SimpleApp& app, MapService& mapService, PlaceDB& placeDb);
    
    // 鏁版嵁瀵煎叆鍔熻兘
    static bool importPlacesFromCSV(PlaceDB& placeDb, const std::string& csvFilePath);
    bool importPlacesMixedMethod(PlaceDB& placeDb, const std::string& csvFilePath, const std::vector<std::string>& placeTypes, int maxPagesPerType = 5);
    static bool createBasicPlacesCSVTemplate(const std::string& csvFilePath);
    
    // 鍦板尯鏁版嵁
    std::string getDistrictData(const std::string& district);

    // 路由设置
    void setupRoutes();
    
    // 内部辅助方法
    nlohmann::json planSingleDestRoute(const nlohmann::json& requestData);
    nlohmann::json planMultiDestRoute(const nlohmann::json& requestData);
    double calculatePathDistance(int startNodeId, int endNodeId);
    double calculatePathTime(int startNodeId, int endNodeId, bool isBiking, bool considerCongestion);
    nlohmann::json findShortestPath(int startNodeId, int endNodeId, bool isBiking, bool isTimeOptimized);
    std::vector<int> solveTSP(const std::vector<std::vector<double>>& distanceMatrix);
    int findNearestNode(double lng, double lat);
    int findNodeByPlaceName(const std::string& placeName);
    int getPathBetweenNodes(int startNodeId, int endNodeId);
    double getPathCongestion(int pathId, bool isBiking);

    // 校内路网相关API
    crow::response getAllPathNodes();
    crow::response getAllPaths();
    crow::response createPathNode(const std::string& name, const std::string& type, 
                                double longitude, double latitude, int placeId);
    crow::response createPath(const std::string& name, int startNodeId, int endNodeId, 
                            double distance, int walkingTime, int ridingTime, 
                            int allowBike, double congestionBase, int pathLevel, int bidirectional);
    crow::response deletePathNode(int nodeId);
    crow::response deletePath(int pathId);
};

#endif 